package multi_thread.advanced;

import sun.misc.Unsafe;

/**
 * @author Cheng Jun
 * Description: 练习 Unsafe 操作 实例变量
 * @version 1.0
 * @date 2021/9/26 7:06
 */
public class UnsafeExample {

    // Unsafe 操作 实例变量
    private int age = 10;

    public static void main(String[] args) throws Exception {

        UnsafeExample cauchy6317 = new UnsafeExample();
        // 为什么不行，A fatal error has been detected by the Java Runtime Environment:
        // User cauchy6317 = new User();
        // AppBootstrap 加载的类 无法调用 Unsafe.getUnsafe()
        // Unsafe unsafe = Unsafe.getUnsafe();
        // long ageOffset = unsafe.objectFieldOffset(cauchy6317.getClass().getField("age"));
        // unsafe.putInt(ageOffset, 19);
        // System.out.println(cauchy6317.getAge());

        // 获取 Unsafe对象
        Unsafe theUnsafe = UnsafeUtil.theUnsafe();
        long ageOffset = theUnsafe.objectFieldOffset(cauchy6317.getClass().getDeclaredField("age"));
        System.out.println("内存中偏移量 offset：" + ageOffset);
        System.out.println("theUnsafe.getInt(cauchy6317, ageOffset) ===>" + theUnsafe.getInt(cauchy6317, ageOffset));
        theUnsafe.putInt(cauchy6317, ageOffset, 11);
        int andSetInt = theUnsafe.getAndSetInt(cauchy6317, ageOffset, 12);
        System.out.println("theUnsafe.getAndSetInt(cauchy6317, ageOffset, 12)===>" + andSetInt);
        int andAddInt = theUnsafe.getAndAddInt(cauchy6317, ageOffset, 12);
        System.out.println("theUnsafe.getAndAddInt(cauchy6317, ageOffset, 12)===>" + andAddInt);
        System.out.println("theUnsafe.getAndAddInt ===>" + cauchy6317.getAge());
        theUnsafe.compareAndSwapInt(cauchy6317, ageOffset, cauchy6317.getAge(), 10);
        System.out.println("theUnsafe.compareAndSwapInt===>" + cauchy6317.getAge());
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

// User cauchy6317 = new User(); 为什么这样不行 System.out.println(cauchy6317.getAge());
class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}